module konsol_gosterici;

/**
 * Oyunun kullanıcıyla konsoldan etkileşimini yönetir.
 */

import std.stdio;
import std.conv;
import std.string;
import std.algorithm;
import std.array;
import kutu_durumu;
import gosterici;

enum kapalıKutuGörüntüsü = "_";

class KonsolGösterici : Gösterici
{
    void mesajVer(string mesaj)
    {
        write(mesaj);
    }

    private
    size_t[] numaralarOkumayıDene()
    {
        mesajVer("Seçiminiz? ");

        string[] sözcükler = readln.strip.split;
        size_t[] numaralar;

        foreach (sözcük; sözcükler) {
            scope (failure)
                mesajVer(format("%s yasal bir numara değil. ", sözcük));
            numaralar ~= sözcük.to!size_t;
        }

        // Tekrarlanan numaralardan kurtulalım
        numaralar = numaralar.sort.uniq.array;

        if (numaralar.length > 2) {
            mesajVer("Lütfen 1 veya 2 numara giriniz. ");
            throw new Exception("Geçersiz sayıda numara");
        }

        return numaralar;
    }

    size_t[] numaralarOku()
    {
        size_t[] numaralar;
        bool başarılıOkundu_mu = false;

        do {
            try {
                numaralar = numaralarOkumayıDene();
                başarılıOkundu_mu = true;

            } catch (Exception hata) {
                // Hatayı gözardı et; tekrar okuyacağız
                başarılıOkundu_mu = false;
            }
        } while (!başarılıOkundu_mu);

        return numaralar;
    }

    void değişti(const KutuDurumu[] kutular)
    {
        writeln();

        foreach (i, durum; kutular) {
            // Burada 'final switch' de düşünülebilirdi
            write((durum == KutuDurumu.açık
                   ? (i + 1).to!string
                   : kapalıKutuGörüntüsü), ' ');
        }

        writeln();
    }

    void zarAtıldı(const size_t[] zarlar)
    {
        immutable zarToplamı = reduce!((a, b) => a + b)(cast(size_t)0, zarlar);

        mesajVer(format("Zarlar: %([%s]%|%), Toplam: %s, ",
                        zarlar, zarToplamı));
    }
}
